home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / term / mif.trm < prev    next >
Text File  |  1993-09-15  |  20KB  |  637 lines

  1. /* GNUPLOT -- mif.trm */
  2. /*
  3.  * Copyright (C) 1992, 1993
  4.  *
  5.  * Permission to use, copy, and distribute this software and its
  6.  * documentation for any purpose with or without fee is hereby granted, 
  7.  * provided that the above copyright notice appear in all copies and 
  8.  * that both that copyright notice and this permission notice appear 
  9.  * in supporting documentation.
  10.  *
  11.  * Permission to modify the software is granted, but not the right to
  12.  * distribute the modified code.  Modifications are to be distributed 
  13.  * as patches to released version.
  14.  *  
  15.  * This software  is provided "as is" without express or implied warranty.
  16.  * 
  17.  * This file is included by ../term.c.
  18.  *
  19.  * This terminal driver was developed for
  20.  *      gnuplot for unix version 3.0 (patchlevel 1)
  21.  *      gnuplot for unix version 3.2 (patchlevel 2)
  22.  *
  23.  * This terminal driver supports:
  24.  *      Frame Maker MIF format version 3.00
  25.  *
  26.  * Options for this terminal driver (set terminal mif [options]):
  27.  *      colour /        Draw primitives with line types >= 0 in colour (sep. 2-7)
  28.  *      monochrome      Draw primitives in black (sep. 0)
  29.  *
  30.  *      polyline /      Draw lines as continous curves
  31.  *      vectors         Draw lines as collections of vectors
  32.  *
  33.  *      help / ?        Print short usage description on stderr
  34.  *
  35.  * Properties for this terminal driver:
  36.  *     -Gnuplot size of worksheet:              MIF_XMAX * MIF_YMAX
  37.  *     -Unit in MIF output:                     cm
  38.  *     -Plot primitives with the same pen will
  39.  *      be grouped in the same MIF group.
  40.  *     -Plot primitives with line types >= 0
  41.  *      will as default be drawn in colour.
  42.  *     -Lines are plotted as collections of
  43.  *      vectors, or as continous lines (default)
  44.  *     -Plot primitives in a plot will be in a
  45.  *      Frame in MIF. Several plot Frames will
  46.  *      be collected in one large Frame.
  47.  *     -Point size of MIF output characters:    MIF_PSIZE
  48.  *     -Used font for MIF output characters:    Times
  49.  *     -Supports vertical text
  50.  *
  51.  * AUTHORS:
  52.  *      Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden
  53.  * 
  54.  * COMMENTS:
  55.  *      Send comments and/or suggestions to olof@fysik4.kth.se
  56.  * 
  57.  * CHANGES:
  58.  *      Changed order of routine declarations.          olof@fysik4.kth.se
  59.  *      Changed mechanism for pen pattern selection.    kssingvo@immd4.informatik.uni-erlangen.de
  60.  *      Support for vertical text.                      kssingvo@immd4.informatik.uni-erlangen.de
  61.  *      Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se
  62.  *
  63.  */
  64. #if !defined(cfree)
  65. #define cfree free
  66. #endif
  67.  
  68. /** Coordinates **/
  69. #define GNP_TO_MIF(P)   (((float) (P)) / 1000.0)        /* Converts gnuplot units to MIF units */
  70. #define MIF_XMAX 15000                  /* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */
  71. #define MIF_YMAX 10000                  /* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */
  72.  
  73. #define MIF_XLAST (MIF_XMAX - 1)
  74. #define MIF_YLAST (MIF_YMAX - 1)
  75.  
  76. static struct mif_line { /* Line point structure specification */
  77.     float fpos_x;           /* Line point X coordinate */
  78.     float fpos_y;           /*            Y coordinate */
  79.     struct mif_line *next;  /* Pointer to next line point */
  80.     struct mif_line *prev;  /* Pointer to previous line point */
  81. } mif_line = { /* Current position structure. Adjust for orign. Local for this file. */
  82.     GNP_TO_MIF(0),
  83.     GNP_TO_MIF(MIF_YLAST),
  84.     &mif_line,
  85.     &mif_line
  86. };
  87.  
  88. /** Characters **/
  89. #define MIF_PSIZE 9                     /* Point size of used characters */
  90.  
  91. #define MIF_VCHAR (MIF_YMAX/31)         /* Distance between rows (a guess) */
  92. #define MIF_HCHAR (MIF_XMAX/95)         /* Distance between characters (a guess) */
  93.  
  94. /** Scale marks **/
  95. #define MIF_VTIC  (MIF_YMAX/150)        /* Size of scale mark (vert) */
  96. #define MIF_HTIC  (MIF_XMAX/225)        /* Size of scale mark (hor) */
  97.  
  98. /** Drawing properties **/
  99. static char mif_justify[64];                    /* How to justify the used text */
  100. static char mif_pen[64], mif_pen_width[64], mif_separation[64];         /* How to plot */
  101.  
  102. #define MIF_TEXT_HOR  0
  103. #define MIF_TEXT_VER  1
  104. static int mif_text_ang = MIF_TEXT_HOR;         /* Rotation angle of text */
  105.  
  106. #define MIF_NPENS 16                    /* Number of MIF pen types */
  107. static int mif_pentype = 0;             /* Pen type to use. Also used to create groups for graphics */
  108. #define MIF_PEN_TO_GROUP(P)     ( 1 + (P) )     /* Map pen type to group number. Must be >= 1 */
  109.  
  110. static int mif_pattern_table[MIF_NPENS] = {     /* Table, which pattern should be used for drawing */
  111.     0,                          /* border  */
  112.     1,                          /* not used */
  113.     2, 3, 4, 8, 12, 13,         /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */
  114.     5,                          /* grid */
  115.     9, 10, 11, 12, 13, 14, 15   /* not used */
  116. };
  117.  
  118. /** MIF groups administration **/
  119. #define MIF_NGROUP_ID           20
  120. static struct mif_group_id {
  121.     int group_existance;
  122. #define MIF_GROUP_EXISTS        1       /* This group id should generate a MIF group */
  123. #define MIF_GROUP_NOT_EXISTS    0       /* This group id should not generate a MIF group */
  124.  
  125.     int group_id;
  126. #define MIF_INVALID_GROUP_ID    0       /* An invalid MIF group ID */
  127.  
  128. } mif_group_id[MIF_NGROUP_ID];            /* List of used group ID:s and corresponding MIF groups existance */
  129.  
  130. /** Semaphores **/
  131. static int mif_initialized = 0;        /* != 0 when output is active */
  132. static int mif_in_frame = 0;            /* != 0 when inside a plot frame */
  133. static int mif_frameno = -1;            /* Current frame number */
  134. static int mif_colour = TRUE;           /* == TRUE when colour should be used */
  135. static int mif_polyline = TRUE;         /* == TRUE when lines are drawn as continous curves */
  136.  
  137. /** Declaration of routine/s for internal use **/
  138. static int insert_mif_line(), proc_group_id();
  139.  
  140. /** Routine/s **/
  141.  
  142. /* Called when this terminal type is set in order to parse options */
  143. MIF_options()
  144. {
  145.     extern char term_options[];     /* Declared in ../setshow.c */
  146.  
  147.     if (!END_OF_COMMAND) {
  148.         /* Colour options */
  149.         if (!END_OF_COMMAND && almost_equals(c_token, "m$onochrome")) {    /* Compare up to $ */
  150.             mif_colour = FALSE;
  151.             c_token++;
  152.         }
  153.         if (!END_OF_COMMAND && almost_equals(c_token, "c$olour")) {   /* Compare up to $ */
  154.             mif_colour = TRUE;
  155.             c_token++;
  156.         }
  157.  
  158.         /* Curve options */
  159.         if (!END_OF_COMMAND && almost_equals(c_token, "v$ectors")) {   /* Compare up to $ */
  160.             mif_polyline = FALSE;
  161.             c_token++;
  162.         }
  163.         if (!END_OF_COMMAND && almost_equals(c_token, "p$olyline")) {   /* Compare up to $ */
  164.             mif_polyline = TRUE;
  165.             c_token++;
  166.         }
  167.  
  168.         /* Short help */
  169.         if ( !END_OF_COMMAND &&
  170.              (almost_equals(c_token, "h$elp") ||
  171.               almost_equals(c_token, "?$")) ) { /* Compare up to $ */
  172.             fprintf(stderr, "Usage: set terminal mif [options]\n");
  173.             fprintf(stderr, "\toptions:\n");
  174.             fprintf(stderr, "\t\tcolour /        Draw primitives with line types >= 0 in colour (sep. 2-7)\n");
  175.             fprintf(stderr, "\t\tmonochrome      Draw primitives in black (sep. 0)                        \n");
  176.             fprintf(stderr, "\n");
  177.             fprintf(stderr, "\t\tpolyline /      Draw lines as continous curves                           \n");
  178.             fprintf(stderr, "\t\tvectors         Draw lines as collections of vectors                     \n");
  179.             fprintf(stderr, "\n");
  180.             fprintf(stderr, "\t\thelp / ?        Print short usage description on stderr                  \n");
  181.  
  182.             c_token++;
  183.         }
  184.     }
  185.  
  186.     sprintf(term_options, "%s %s", (mif_colour == TRUE)? "colour": "monochrome",
  187.                        (mif_polyline == TRUE)? "polyline": "vectors");
  188. }
  189.  
  190. /* Deallocate the used line structure elements */
  191. static int free_mif_line()
  192. {
  193.     struct mif_line *tline;
  194.  
  195.     while (mif_line.prev != &mif_line) {
  196.         /* Unlink */
  197.         tline = mif_line.prev;
  198.         mif_line.prev = mif_line.prev->prev;
  199.         mif_line.prev->next = &mif_line;
  200.  
  201.         /* Deallocate */
  202.         free(tline);
  203.     }
  204.  
  205.     /* Make sure that the list will be empty */
  206.     mif_line.prev = &mif_line;
  207.     mif_line.next = &mif_line;
  208. }
  209.  
  210. /* Draw the pending line. Change current position. */
  211. static int put_mif_line()
  212. {
  213.     int np, i;
  214.     struct mif_line *tline;
  215.  
  216.     /* Process if inside a Frame */
  217.     if (mif_initialized != 0 && mif_in_frame != 0) {
  218.  
  219.         /* Count the number of available points */
  220.         for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++)
  221.             ;
  222.  
  223.         /* Draw line (at least two points) */
  224.         if (np >= 2) {
  225.             /* Line preamble */
  226.             fprintf(outfile, "\t<PolyLine <GroupID %d> %s %s %s\n",
  227.                      MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
  228.  
  229.             /* Draw the line elements */
  230.             fprintf(outfile, "\t\t<NumPoints %d> ", np);
  231.             for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) {
  232.                 if (i%4 == 0)
  233.                     fprintf(outfile, "\n\t\t");
  234.                 fprintf(outfile, "<Point  %.3f %.3f> ", tline->fpos_x, tline->fpos_y);
  235.             }
  236.  
  237.             /* Line post amble */
  238.             fprintf(outfile, "\n\t>\n");
  239.  
  240.             /* Register the used group ID */
  241.             proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  242.  
  243.             /* Avoid to redraw this. The MIF system should remember it. */
  244.             mif_pen[0] = '\0';
  245.             mif_pen_width[0] = '\0';
  246.             mif_separation[0] = '\0';
  247.  
  248.             /* Move current position to end of line */
  249.             mif_line.fpos_x = mif_line.prev->fpos_x;
  250.             mif_line.fpos_y = mif_line.prev->fpos_y;
  251.  
  252.             /* Restore the line */
  253.             free_mif_line();
  254.         }
  255.  
  256.     } /* Line processed */
  257. }
  258.  
  259. /* Set up a MIF output file */
  260. MIF_init()
  261. {
  262.     int i;
  263.  
  264.     extern char version[];        /* Declared in ../version.c */
  265.     extern char patchlevel[];
  266.  
  267.     /* Process if not inside a MIF file and Frame */
  268.     if (mif_initialized == 0 && mif_in_frame == 0) {
  269.         /* Tell this terminal driver that the output is initialized and no current frames are processed */
  270.         mif_initialized = 1;
  271.         mif_in_frame = 0;
  272.  
  273.         /* Reset internal position */
  274.         free_mif_line();
  275.         mif_line.fpos_x = GNP_TO_MIF(0);
  276.         mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
  277.  
  278.         /* Reset drawing properties strings */
  279.         mif_pen[0] = '\0';
  280.         mif_pen_width[0] = '\0';
  281.         mif_separation[0] = '\0';
  282.         sprintf(mif_justify, " <TLAlignment Left> ");
  283.  
  284.         /* Reset group ID generator */
  285.         for (i = 0; i < MIF_NGROUP_ID; i++) {
  286.             mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
  287.             mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  288.         }
  289.  
  290.         /* Identify ourselves */
  291.         fprintf(outfile, "<MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n", version, patchlevel);
  292.         fprintf(outfile, "#\n");
  293.  
  294.         /* Setup a default environment to use */
  295.         fprintf(outfile, "# Set a default pen pattern, pen width, unit and font for subsequent objects\n");
  296.         fprintf(outfile, "<Pen 0>\n");
  297.         fprintf(outfile, "<Fill 15>\n");
  298.         fprintf(outfile, "<PenWidth 0.5 pt>\n");
  299.         fprintf(outfile, "<Separation 0>\n");
  300.         fprintf(outfile, "<Units Ucm>\n");
  301.         fprintf(outfile, "<Font <FFamily `Times'> <FSize %d> <FPlain Yes>>\n", MIF_PSIZE);
  302.         fprintf(outfile, "#\n");
  303.     } /* MIF file created */
  304. }
  305.  
  306. /* Finish of a MIF output file */
  307. MIF_reset()
  308. {
  309.     /* Process if inside a MIF file and not inside a Frame */
  310.     if (mif_initialized != 0 && mif_in_frame == 0) {
  311.         /* Finish off the MIF file */
  312.         fprintf(outfile, "#\n");
  313.         fprintf(outfile, "# End of MIFFile\n");
  314.  
  315.         /* Tell this terminal driver that the output is finished */
  316.         mif_initialized = 0;
  317.     } /* MIF file finished */
  318. }
  319.  
  320. /* Start plotting a Frame (-> graphics mode) */
  321. MIF_graphics()
  322. {
  323.     int i;
  324.  
  325.     /* Process if not inside a Frame */
  326.     if (mif_initialized != 0 && mif_in_frame == 0) {
  327.         /* Tell that this terminal driver is working with a plot frame */
  328.         mif_in_frame = 1;
  329.  
  330.         /* Update frame number */
  331.         mif_frameno++;
  332.  
  333.         /* Set current position */
  334.         free_mif_line();
  335.         mif_line.fpos_x = GNP_TO_MIF(0);
  336.         mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
  337.  
  338.         /* Set drawing properties */
  339.         mif_pen[0] = '\0';
  340.         mif_pen_width[0] = '\0';
  341.         mif_separation[0] = '\0';
  342.         sprintf(mif_justify, " <TLAlignment Left> ");
  343.  
  344.         /* Reset group ID generator */
  345.         for (i = 0; i < MIF_NGROUP_ID; i++) {
  346.             mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
  347.             mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  348.         }
  349.  
  350.         /* Frame preamble */
  351.         fprintf(outfile, "#\n");
  352.         fprintf(outfile, "# Frame number %d with plot of graphics\n", mif_frameno);
  353.         fprintf(outfile, "<Frame\n");
  354.         fprintf(outfile, "\t<Pen 15>\n");
  355.         fprintf(outfile, "\t<Fill 15>\n");
  356.         fprintf(outfile, "\t<PenWidth  0.5 pt>\n");
  357.         fprintf(outfile, "\t<Separation 0>\n");
  358.         fprintf(outfile, "\t<BRect 0.000 %.3f %.3f %.3f>\n",
  359.                  ((float) mif_frameno)*GNP_TO_MIF(MIF_YMAX+100), GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX));
  360.         fprintf(outfile, "\t<NSOffset  0.000>\n");
  361.         fprintf(outfile, "\t<BLOffset  0.000>\n");
  362.     } /* Frame created */
  363. }
  364.  
  365. /* Stop plotting a Frame (-> text mode) */
  366. MIF_text()
  367. {
  368.     int i;
  369.  
  370.     /* Process if inside a Frame */
  371.     if (mif_initialized != 0 && mif_in_frame != 0) {
  372.  
  373.         /* Draw pending line */
  374.         if (mif_polyline == TRUE)
  375.             put_mif_line();
  376.  
  377.         /* Group the used plot primitives */
  378.         fprintf(outfile, "\t#\n");
  379.         fprintf(outfile, "\t# Group the the objects in groups to make the chart easier to manipulate\n");
  380.         fprintf(outfile, "\t# after it's imported into FrameMaker.\n");
  381.  
  382.         for (i = 0; i < MIF_NGROUP_ID; i++) {
  383.             if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
  384.                 mif_group_id[i].group_existance == MIF_GROUP_EXISTS) {
  385.                 fprintf(outfile, "\t<Group\n");
  386.                 fprintf(outfile, "\t\t<ID %d>\n", mif_group_id[i].group_id);
  387.                 fprintf(outfile, "\t>\n");
  388.             }
  389.         }
  390.  
  391.         /* Frame post amble */
  392.         fprintf(outfile, ">\n");
  393.         fprintf(outfile, "# End of Frame number %d\n", mif_frameno);
  394.         fprintf(outfile, "#\n");
  395.  
  396.         /* Tell that this terminal driver is not working with a plot frame */
  397.         mif_in_frame = 0;
  398.     } /* Frame finshed */
  399. }
  400.  
  401. /* Select type of line in grapics */
  402. /* NOTE: actually written to output the first time a primitive is drawn AFTER this call */
  403. MIF_linetype(linetype)
  404. int linetype;           /* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */
  405. {
  406.     /* Process if inside a Frame */
  407.     if (mif_initialized != 0 && mif_in_frame != 0) {
  408.  
  409.         /* Draw pending line */
  410.         if (mif_polyline == TRUE)
  411.             put_mif_line();
  412.  
  413.         /* Translate gnuplot pen types to MIF pen types */
  414.         if (linetype < 0) {     /* Special lines */
  415.             if (linetype == -1) {
  416.                 mif_pentype = 8+MIF_NPENS;      /* -1 */
  417.                 if (mif_colour == TRUE)
  418.                     sprintf(mif_separation, " <Separation 0> ");
  419.             }
  420.             else {
  421.                 mif_pentype = 0+MIF_NPENS;      /* -2 or less */
  422.                 if (mif_colour == TRUE)
  423.                     sprintf(mif_separation, " <Separation 0> ");
  424.             }
  425.             sprintf(mif_pen_width, " <PenWidth 1.0 pt> ");
  426.         }
  427.         else {                  /* Normal lines */
  428.             mif_pentype = (linetype)%MIF_NPENS;     /* 0-(MIF_NPENS-1) */
  429.             sprintf(mif_pen_width, " <PenWidth 0.5 pt> ");
  430.             if (mif_colour == TRUE)
  431.                 sprintf(mif_separation, " <Separation %d> ", 2+(mif_pentype%6));        /* 2-7 */
  432.         }
  433.  
  434.         /* Set pen type */
  435.         sprintf(mif_pen, " <Pen %d> ", mif_pattern_table[mif_pentype%MIF_NPENS]);
  436.  
  437.     } /* Primitive processed */
  438. }
  439.  
  440. /* Draw the text horisontally or vertically (90 degrees counterclockwise) */
  441. int MIF_text_angle(ang)
  442. int ang;
  443. {
  444.     if (ang != 0)
  445.     mif_text_ang = MIF_TEXT_VER;
  446.     else
  447.     mif_text_ang = MIF_TEXT_HOR;
  448.  
  449.     return(TRUE);
  450. }
  451.  
  452. /* Justify following text lines (MIF_put_text()) relative to the insertion point */
  453. MIF_justify_text(mode)
  454. /* NOTE: actually written to output in text primitives which are drawn AFTER this call */
  455. enum JUSTIFY mode;
  456. {
  457.     int rval = TRUE;
  458.  
  459.     /* Process if inside a Frame */
  460.     if (mif_initialized != 0 && mif_in_frame != 0) {
  461.         switch (mode) {
  462.         case LEFT:
  463.             sprintf(mif_justify, " <TLAlignment Left> ");
  464.             break;
  465.         case CENTRE:
  466.             sprintf(mif_justify, " <TLAlignment Center> ");
  467.             break;
  468.         case RIGHT:
  469.             sprintf(mif_justify, " <TLAlignment Right> ");
  470.             break;
  471.         default:
  472.             rval = FALSE;
  473.             break;
  474.         }
  475.  
  476.     } /* Primitive processed */
  477.     else {
  478.         rval = FALSE;
  479.     }
  480.  
  481.     return(rval);
  482. }
  483.  
  484. /* Draw a vector from current position to (x, y) and change current position. */
  485. /* NOTE: actually written to output the first time another primitive is called AFTER this call */
  486. MIF_vector(x, y)
  487. unsigned int x, y;
  488. {
  489.     /* Process if inside a Frame */
  490.     if (mif_initialized != 0 && mif_in_frame != 0) {
  491.  
  492.         /* Setup the vector as a part of the line */
  493.         insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST-(int)y));
  494.  
  495.         /* Draw pending line -> vector */
  496.         if (mif_polyline == FALSE)
  497.             put_mif_line();
  498.  
  499.     } /* Vector processed */
  500. }
  501.  
  502. /* Move current position */
  503. MIF_move(x, y)
  504. unsigned int x, y;
  505. {
  506.     /* Process if inside a Frame */
  507.     if (mif_initialized != 0 && mif_in_frame != 0) {
  508.  
  509.         /* Draw pending line */
  510.         if (mif_polyline == TRUE)
  511.             put_mif_line();
  512.  
  513.         mif_line.fpos_x = GNP_TO_MIF(x);
  514.         mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST-(int)y);
  515.     }
  516. }
  517.  
  518. /* Draw the text string str at (x, y). Adjust according to MIF_justify_text(). Change current position. */
  519. MIF_put_text(x, y, str)
  520. unsigned int x, y;
  521. char str[];
  522. {
  523.     /* Process if inside a Frame */
  524.     if (mif_initialized != 0 && mif_in_frame != 0) {
  525.  
  526.         /* Draw pending line */
  527.         if (mif_polyline == TRUE)
  528.             put_mif_line();
  529.  
  530.         /* Adjust current position for text-graphics alignment */
  531.         MIF_move(x, y-MIF_VCHAR/5);
  532.  
  533.         if (strlen(str) > 0) {
  534.  
  535.             /* Draw the text */
  536.             fprintf(outfile, "\t<TextLine <GroupID %d> %s %s %s\n",
  537.                      MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
  538.             fprintf(outfile, "\t\t<TLOrigin  %.3f %.3f> %s %s <String `%s'>\n",
  539.                      mif_line.fpos_x, mif_line.fpos_y, mif_justify,
  540.                      (mif_text_ang == MIF_TEXT_VER)? "<Angle 90>": "",
  541.                      str);
  542.             fprintf(outfile, "\t>\n");
  543.  
  544.             /* Register the used group ID */
  545.             proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
  546.  
  547.             /* Avoid to redraw this. The MIF system should remember it. */
  548.             mif_pen[0] = '\0';
  549.             mif_pen_width[0] = '\0';
  550.             mif_separation[0] = '\0';
  551.  
  552.             mif_justify[0] = '\0';  /* Independent of linetype */
  553.         }
  554.     } /* Text processed */
  555. }
  556.  
  557.  
  558. /* Insert one point in the line */
  559. static int insert_mif_line(fx, fy)
  560. float fx, fy;
  561. {
  562.     int rval = TRUE;
  563.  
  564.     if ((mif_line.prev->next = (struct mif_line *) alloc(sizeof(struct mif_line),"MIF driver")) != (struct mif_line *) NULL) {
  565.         /* Link */
  566.         mif_line.prev->next->next = &mif_line;
  567.         mif_line.prev->next->prev = mif_line.prev;
  568.         mif_line.prev = mif_line.prev->next;
  569.  
  570.         /* Fill */
  571.         mif_line.prev->fpos_x = fx;
  572.         mif_line.prev->fpos_y = fy;
  573.  
  574.         rval = TRUE;
  575.     }
  576.     else { /* Failed to allocate */
  577.         /* Relink */
  578.         mif_line.prev->next = &mif_line;
  579.  
  580.         rval = FALSE;
  581.     }
  582.  
  583.     return(rval);
  584. }
  585.  
  586.  
  587. /* Register group ID. Update group ID existance. */
  588. /* Returns:     1       group_id belongs to a MIF group
  589.         0       group_id does not belong to a MIF group
  590.            -1       not inside a Frame
  591.            -2       group ID list is full
  592.  */
  593. static int proc_group_id(group_id)
  594. int group_id;
  595. {
  596.     int i, rval = 0;
  597.  
  598.     /* Process if inside a Frame */
  599.     if (mif_initialized != 0 && mif_in_frame != 0) {
  600.  
  601.         /* Find out the group ID, or a free group ID slot index. */
  602.         for (i = 0; i < MIF_NGROUP_ID &&
  603.                 mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
  604.                 mif_group_id[i].group_id != group_id;
  605.                                         i++) {
  606.             /* Don't check the group_existance variable */
  607.         }
  608.  
  609.         if (i < MIF_NGROUP_ID) {
  610.             if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) {
  611.                 /* Register as new group ID for eventual use as MIF group */
  612.                 mif_group_id[i].group_id = group_id;
  613.                 mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
  614.             }
  615.             else {
  616.                 /* If second use of this group ID -> create a new MIF group */
  617.                 if (mif_group_id[i].group_id == group_id) {
  618.                     mif_group_id[i].group_existance = MIF_GROUP_EXISTS;
  619.                     /* NOTE: a group MUST have at least two members. */
  620.                     rval = 1;
  621.                 }
  622.             }
  623.         }
  624.         else {
  625.             rval = -2;      /* No place for this group ID in the list */
  626.         }
  627.  
  628.     } /* Group ID processed */
  629.     else {
  630.         rval = -1;      /* Not inside a Frame */
  631.     }
  632.  
  633.     /* Return MIF group status */
  634.     return(rval);
  635. }
  636.  
  637.